package com.rental.houses.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rental.common.constant.RedisConstant;
import com.rental.common.exception.ProjectException;
import com.rental.common.result.ResultCodeEnum;
import com.rental.houses.mapper.SubletHourseMapper;
import com.rental.houses.service.ISubletHourseService;
import com.rental.model.entity.house.SubletHourse;
import com.rental.model.form.house.SubletHouseAddForm;
import com.rental.model.form.house.SubletHousePageForm;
import com.rental.model.vo.house.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-01-16
 */
@Service
public class SubletHourseServiceImpl extends ServiceImpl<SubletHourseMapper, SubletHourse> implements ISubletHourseService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取转租房屋分页列表
     *
     * @param page                当前页码
     * @param size                每页记录数
     * @param subletHousePageForm 查询条件
     * @return 分页结果
     */
    @Override
    public Page<SubletHousePageVo> getSubletHousePage(Integer page, Integer size, SubletHousePageForm subletHousePageForm) {
        Page<SubletHousePageVo> pageVo = new Page<>(page, size);
        pageVo = this.baseMapper.getSubletHousePage(pageVo, subletHousePageForm.getKeyword(), subletHousePageForm.getStructure(), subletHousePageForm.getRent());
        return pageVo;
    }

    /**
     * 获取转租房屋详情
     *
     * @param id 转租房屋id
     * @return 转租房屋详情
     */
    @Override
    public SubletHouseInfoVo getSubletHouseInfoById(Long id, Long uid) {
        addViewCount(id);
        SubletHouseInfoVo result = this.baseMapper.getSubletHouseInfoById(id);
        // 判断是否收藏
        Double score = redisTemplate.boundZSetOps(RedisConstant.USER_COLLECTION_KEY + uid).score(HouseTypeVo.build(2, id));
        if (score != null) {
            result.setIsCollected(1);
        } else {
            result.setIsCollected(0);
        }
        // 浏览记录
        redisTemplate.boundZSetOps(RedisConstant.USER_VISIT_HISTORY_KEY + uid).add(HouseTypeVo.build(2, id), System.currentTimeMillis());
        return result;
    }

    /**
     * 浏览数+1
     *
     * @param id 转租房屋id
     */
    private void addViewCount(Long id) {
        LambdaUpdateWrapper<SubletHourse> set = Wrappers.lambdaUpdate(SubletHourse.class)
                .eq(SubletHourse::getId, id)
                .setSql("view_count = view_count + 1");
        this.update(set);
    }

    /**
     * 获取联系微信
     *
     * @param id 转租房屋id
     * @return 联系微信
     */
    @Override
    public String getContactWechat(Long id) {
        SubletHourse subletHourse = this.getById(id);
        if (subletHourse == null) throw new ProjectException(ResultCodeEnum.DATABASE_NULL);
        String wechat = subletHourse.getWechat();
        if (StringUtils.isBlank(wechat)) throw new ProjectException(ResultCodeEnum.DATABASE_NULL);
        return wechat;
    }

    /**
     * 获取联系电话
     *
     * @param id 转租房屋id
     * @return 联系电话
     */
    @Override
    public String getContactPhone(Long id) {
        SubletHourse subletHourse = this.getById(id);
        if (subletHourse == null) throw new ProjectException(ResultCodeEnum.DATABASE_NULL);
        String phone = subletHourse.getPhone();
        if (StringUtils.isBlank(phone)) throw new ProjectException(ResultCodeEnum.DATABASE_NULL);
        return phone;
    }

    /**
     * 下架房屋
     *
     * @param id  转租房屋id
     * @param uid 用户id
     * @return 下架结果
     */
    @Override
    public Boolean downHouse(Long id, Long uid) {
        LambdaUpdateWrapper<SubletHourse> set = Wrappers.lambdaUpdate(SubletHourse.class)
                .eq(SubletHourse::getId, id)
                .eq(SubletHourse::getUid, uid)
                .set(SubletHourse::getState, 0);
        if (this.update(set)) return true;
        throw new ProjectException(ResultCodeEnum.PERMISSION_ERROR);
    }

    /**
     * 发布转租房屋
     *
     * @param subletHouseAddForm 转租房屋信息
     * @return 发布结果
     */
    @Override
    public Boolean addSubletHouse(SubletHouseAddForm subletHouseAddForm) {
        SubletHourse subletHourse = new SubletHourse();
        subletHourse.setUid(subletHouseAddForm.getUid());
        subletHourse.setLongitude(subletHouseAddForm.getLongitude());
        subletHourse.setLatitude(subletHouseAddForm.getLatitude());
        subletHourse.setLocation(subletHouseAddForm.getLocation());
        subletHourse.setImagesUrl(subletHouseAddForm.getImagesUrl());
        subletHourse.setVideoUrl(subletHouseAddForm.getVideoUrl());
        subletHourse.setNearbyStation(subletHouseAddForm.getNearbyStation());
        subletHourse.setStructure(subletHouseAddForm.getStructure());
        subletHourse.setMale(subletHouseAddForm.getMale());
        subletHourse.setFemale(subletHouseAddForm.getFemale());
        subletHourse.setIntroduce(subletHouseAddForm.getIntroduce());
        subletHourse.setRent(subletHouseAddForm.getRent());
        subletHourse.setTenancyTerm(subletHouseAddForm.getTenancyTerm());
        subletHourse.setPayType(subletHouseAddForm.getPayType());
        subletHourse.setRenterRequire(subletHouseAddForm.getRenterRequire());
        subletHourse.setLandlord(subletHouseAddForm.getLandlord());
        subletHourse.setContractExpiration(subletHouseAddForm.getContractExpiration());
        subletHourse.setMoveTime(subletHouseAddForm.getMoveTime());
        subletHourse.setVisitingTime(subletHouseAddForm.getVisitingTime());
        subletHourse.setPhone(subletHouseAddForm.getPhone());
        subletHourse.setWechat(subletHouseAddForm.getWechat());
        subletHourse.setEndTime(subletHouseAddForm.getEndTime());
        subletHourse.setTitle(subletHouseAddForm.getTitle());
        subletHourse.setOccupancy(subletHourse.getMale() + subletHourse.getFemale());
        if (this.save(subletHourse)) {
            // 将发布的房屋id存入Redis
            redisTemplate.boundZSetOps(RedisConstant.USER_PUBLISH_KEY + subletHouseAddForm.getUid()).add(HouseTypeVo.build(2, subletHourse.getId()), System.currentTimeMillis());
            // 保存位置信息至Redis
            redisTemplate.boundGeoOps(RedisConstant.HOUSE_LOCATION_KEY)
                    .add(new Point(subletHourse.getLongitude().doubleValue(), subletHourse.getLatitude().doubleValue()), HouseTypeVo.build(2, subletHourse.getId()));

            return true;
        }
        throw new ProjectException(ResultCodeEnum.DATABASE_INSERT_ERROR);
    }

    /**
     * 删除转租房屋
     *
     * @param id  转租房屋id
     * @param uid 用户id
     * @return 删除结果
     */
    @Override
    public Boolean deleteSubletHouse(Long id, Long uid) {
        SubletHourse subletHourse = this.getById(id);
        if (subletHourse == null) throw new ProjectException(ResultCodeEnum.DATABASE_NULL);
        if (uid == null || !uid.equals(subletHourse.getUid()))
            throw new ProjectException(ResultCodeEnum.PERMISSION_ERROR);
        if (subletHourse.getState() == 1) throw new ProjectException(ResultCodeEnum.DATABASE_STATE_NOT_ZERO);
        this.removeById(id);
        // 从Redis中删除发布的房屋id
        HouseTypeVo build = HouseTypeVo.build(2, id);
        redisTemplate.boundZSetOps(RedisConstant.USER_PUBLISH_KEY + uid).remove(build);
        // 从Redis中删除位置信息
        redisTemplate.boundGeoOps(RedisConstant.HOUSE_LOCATION_KEY).remove(build);
        return true;
    }

    /**
     * 获取当前用户的所有转租房屋信息
     *
     * @param uid
     * @return
     */
    @Override
    public List<SubletHourse> getSubletHouseListByUid(Long uid) {
        LambdaQueryWrapper<SubletHourse> eq = new LambdaQueryWrapper<SubletHourse>().eq(SubletHourse::getUid, uid);
        List<SubletHourse> subletHourseList = this.list(eq);
        return subletHourseList;
    }

    /**
     * 收藏转租屋
     *
     * @param id  转租房屋id
     * @param uid 用户id
     * @return 收藏结果
     */
    @Override
    public Boolean collectHouse(Long id, Long uid) {
        return redisTemplate.boundZSetOps(RedisConstant.USER_COLLECTION_KEY + uid).add(HouseTypeVo.build(2, id), System.currentTimeMillis());
    }

    /**
     * 取消收藏转租屋
     *
     * @param id  转租房屋id
     * @param uid 用户id
     * @return 取消收藏结果
     */
    @Override
    public Boolean cancelCollectHouse(Long id, Long uid) {
        redisTemplate.boundZSetOps(RedisConstant.USER_COLLECTION_KEY + uid).remove(HouseTypeVo.build(2, id));
        return true;
    }

    /**
     * 获取转租房屋简介
     *
     * @param id    转租房屋id
     * @param state 上下架状态
     * @return 转租房屋简介
     */
    @Override
    public SubletHousePageVo getSubletHousePageVo(Long id, Integer state) {
        if (state == 0) state = null;
        return this.baseMapper.getSubletHousePageVo(id, state);
    }

    /**
     * 获取有效转租房源数
     *
     * @return 有效转租房源数
     */
    @Override
    public Long getCount() {
        LambdaQueryWrapper<SubletHourse> eq = Wrappers.lambdaQuery(SubletHourse.class)
                .eq(SubletHourse::getState, 1);
        return this.count(eq);
    }

    /**
     * 举报转租房屋
     *
     * @param id     房屋id
     * @param userId 用户id
     * @return 举报后的房屋举报数
     */
    @Override
    public Integer accusation(Long id, Long userId) {
        SubletHourse byId = this.getById(id);
        if (byId == null) return null;
        byId.setAccusation(byId.getAccusation() + 1);
        this.updateById(byId);
        return byId.getAccusation();
    }


}
